home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
Sherlock 2.0
/
DevLibSrc
/
Mac DevLib
/
mac_via.c
< prev
Wrap
Text File
|
1995-11-06
|
4KB
|
195 lines
/*
* mac_via.c, adapted from VIA_TIMER.c.
*
* Copyright (c) 1991 Symantec Corporation. All rights reserved.
*
*/
#include <LIBlib.h>
// From <LoMem.h>: Warning: can't be used on a Power Mac.
// #include <LoMem.h>
#include <Memory.h>
#define Declare_LoMem(type, name, address) type (name) : (address)
Declare_LoMem(THz, ApplZone, 0x2AA);
Declare_LoMem(Ptr, VIA, 0x1D4);
#ifdef THINK_C
ProcPtr Lvl1DT[] : 0x192;
ProcPtr Lvl2DT[] : 0x1B2;
#endif
#include <Memory.h> /* VIA */
#include <stdlib.h>
#include <profile.h>
#define vT1C (512*4)
#define vT1CH (512*5)
#define vIER (512*14)
struct words { short hi, lo; };
struct bytes { char hi, lo; };
/* tick count */
static union {
long dword;
struct words word;
} elapsed;
/* VIA countdown timer #1 */
static union {
short word;
struct bytes byte;
} timer;
static struct {
ProcPtr vector;
char enable;
} save;
static Boolean timer_running, exithook_installed;
/*
* VIA_ticks - return tick count
*
* Each tick represents approximately 1.28 micro-seconds.
*
*/
void my_start_VIA_timer(int flag);
long
VIA_ticks()
{
long entry_dword = elapsed.dword;
if (!timer_running)
my_start_VIA_timer(FALSE);
/* Wait for the high byte of the countdown timer to change. */
do {
timer.byte.hi = VIA[vT1CH];
timer.byte.lo = VIA[vT1C];
} while (timer.byte.hi != VIA[vT1CH]);
/* This sets only the low part. The high part is set by the rollover. */
elapsed.word.lo = ~timer.word;
#if 0 /* new code: doesn't seem to work at all. */
if (elapsed.dword < entry_dword) {
es("VIA_TICKS: adjusting...");
#if 0
es("VIA[vIER]: "); ehex(VIA[vIER] & 0xff);
#endif
es(" entry elapsed: "); ehex(entry_dword);
es(" elapsed: "); ehex(elapsed.dword);
elapsed.word.hi++;
VIA[vIER] = 0xC0;
VIA[vT1C] = VIA[vT1CH] = ~0;
#if 0 /* This always prints as f3, not c0! */
es("new VIA[vIER]: "); ehex(VIA[vIER] & 0xff);
#endif
enl();
}
#endif
#if 0 /* Hangs */
ecnl(); es("VIA: "); ehex(elapsed.dword); enl();
#endif
return(elapsed.dword);
}
/*
Compensate for a presumably missed rollover interrup.
*/
long my_VIA_rollover(void);
long
my_VIA_rollover(void)
{
++elapsed.word.hi;
VIA[vT1C] = VIA[vT1CH] = ~0;
return(elapsed.dword);
}
/*
* start_VIA_timer
*
* It is not necessary to call this routine, as it is automatically
* invoked by "VIA_ticks".
*
*/
void
my_start_VIA_timer(int flag)
{
/* install rollover interrupt */
/* This does *not* set the elapsed time. */
VIA[vT1C] = VIA[vT1CH] = ~0;
if (flag == FALSE) {
save.vector = Lvl1DT[6];
save.enable = VIA[vIER];
}
#if 0
else {
ecnl(); es("old vector: "); eptr(save.vector);
es(" old enable: "); ehex(save.enable); enl();
}
#endif
asm {
lea @A5,a0
move.l a5,(a0)
lea @rollover,a0
move.l a0,Lvl1DT[6]
}
VIA[vIER] = 0xC0;
/* arrange for timer to be stopped at exit */
timer_running = true;
if (!exithook_installed) {
_atexit(stop_VIA_timer);
exithook_installed = true;
}
return;
/* interrupt handler */
rollover:
/* Save register. */
asm {
move.l a5,-(sp)
movea.l @A5,a5
}
++elapsed.word.hi;
VIA[vT1C] = VIA[vT1CH] = ~0;
/* Restore register. */
asm {
movea.l (sp)+,a5
rts
A5: dc.l 0 ; store app's A5 here
}
}
/*
* stop_VIA_timer
*
* It is not necessary to call this routine, as it will be called
* automatically at program exit.
*
*/
void
stop_VIA_timer(void)
{
if (timer_running) {
if (!(save.enable & 0x40))
VIA[vIER] = 0x40;
Lvl1DT[6] = save.vector;
timer_running = false;
}
}